// HttpFileServer.cpp
#include "HttpFileServer.h"
#include <WiFi.h>

WebServer fileServer(8080); // HTTP文件服务器端口
String normalizePath(String path)
{
    if (path.length() == 0)
    {
        return "/";
    }

    // 确保路径以斜杠开头
    if (!path.startsWith("/"))
    {
        path = "/" + path;
    }

    // 移除末尾的斜杠（除非是根目录）
    if (path.endsWith("/") && path != "/")
    {
        path = path.substring(0, path.length() - 1);
    }

    return path;
}
void setupHttpFileServer()
{
    // 主页 - 文件浏览器
    fileServer.on("/", HTTP_GET, []()
                  {
    String path = fileServer.hasArg("path") ? fileServer.arg("path") : "/";
    path = normalizePath(path);
    
    String html = R"=====(
<!DOCTYPE html>
<html>
<head>
    <title>ESP32-CAM File Manager</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta charset="UTF-8">
    <style>
        body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 20px; background: #f5f5f5; }
        .container { max-width: 1200px; margin: 0 auto; background: white; padding: 25px; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); }
        .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; padding-bottom: 15px; border-bottom: 2px solid #007bff; }
        .breadcrumb { background: #e9ecef; padding: 12px 15px; border-radius: 8px; margin-bottom: 20px; font-size: 14px; }
        .breadcrumb a { color: #007bff; text-decoration: none; }
        .breadcrumb a:hover { text-decoration: underline; }
        .file-list { list-style: none; padding: 0; margin: 0; }
        .file-item { display: flex; justify-content: space-between; align-items: center; padding: 14px; border-bottom: 1px solid #e9ecef; transition: background 0.2s ease; }
        .file-item:hover { background: #f8f9fa; }
        .file-name { flex: 1; font-size: 16px; }
        .file-name a { color: inherit; text-decoration: none; }
        .file-name a:hover { color: #007bff; }
        .file-size { color: #6c757d; margin-right: 20px; min-width: 80px; text-align: right; font-size: 14px; }
        .file-actions { display: flex; gap: 8px; }
        .btn { padding: 8px 16px; border: none; border-radius: 6px; cursor: pointer; text-decoration: none; display: inline-block; font-size: 14px; font-weight: 500; transition: all 0.2s; }
        .btn-primary { background: #007bff; color: white; }
        .btn-primary:hover { background: #0056b3; }
        .btn-danger { background: #dc3545; color: white; }
        .btn-danger:hover { background: #bb2d3b; }
        .btn-secondary { background: #6c757d; color: white; }
        .btn-secondary:hover { background: #5a6268; }
        .storage-info { background: linear-gradient(135deg, #e7f3ff, #d4e6ff); padding: 20px; border-radius: 10px; margin: 25px 0; border-left: 4px solid #007bff; }
        .progress { width: 100%; background: #dee2e6; border-radius: 8px; margin: 15px 0; height: 24px; overflow: hidden; }
        .progress-bar { height: 100%; background: linear-gradient(90deg, #007bff, #0056b3); border-radius: 8px; transition: width 0.3s ease; }
        .folder { color: #fd7e14; font-weight: 600; }
        .file { color: #495057; }
        .hidden-item { opacity: 0.6; }
        h1 { color: #2c3e50; margin: 0; font-size: 28px; }
        h2 { color: #34495e; margin: 20px 0 15px 0; font-size: 22px; }
        h3 { color: #2c3e50; margin: 0 0 15px 0; font-size: 18px; }
        .no-files { text-align: center; color: #6c757d; padding: 40px; font-style: italic; }
        .system-file { color: #868e96; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>📁 ESP32-CAM File Manager</h1>
            <span style="color: #495057; font-weight: 500;">IP: )=====";
    
    html += WiFi.localIP().toString();
    html += R"=====(</span>
        </div>
        
        <div class="breadcrumb">
            <a href="/">Root</a>)=====";

    html += getBreadcrumb(path);
    
    html += R"=====(
        </div>

        <div class="storage-info">
            <h3>💾 Storage Information</h3>
            <div class="progress">
                <div class="progress-bar" style="width: )=====";
    
    // 存储空间信息
    uint64_t totalBytes = SD_MMC.totalBytes();
    uint64_t usedBytes = SD_MMC.usedBytes();
    float usedPercent = totalBytes > 0 ? (float)usedBytes / totalBytes * 100 : 0;
    
    html += String(usedPercent, 1);
    html += R"=====(%;"></div>
            </div>
            <p style="margin: 0; font-size: 16px; color: #2c3e50;"><strong>Used:</strong> )=====";
    
    html += formatFileSize(usedBytes) + " / " + formatFileSize(totalBytes);
    html += " (" + String(usedPercent, 1) + "%)";
    html += R"=====(</p>
        </div>

        <h2>📋 Files and Folders</h2>
        <ul class="file-list">
    )=====";

    // 列出文件和文件夹
    File dir = SD_MMC.open(path);
    int fileCount = 0;
    
    if (dir) {
        Serial.println("成功打开目录");
        File file = dir.openNextFile();
        while (file) {
            Serial.println("开始遍历目录内容...");
            String fileName = file.name();
            //获取全路径
            String fullPath = path + "/" + fileName;
            String shortName = getFileName(fileName);
            
            Serial.println("找到: " + fileName + 
                          " (目录: " + String(file.isDirectory()) + 
                          ", 大小: " + String(file.size()) + " bytes)");
            
            // 跳过隐藏文件和系统文件
            if (shortName.startsWith(".") || 
                shortName.equals("System Volume Information") ||
                shortName.equals("$RECYCLE.BIN") ||
                shortName.equals("Spotlight-V100") ||
                shortName.equals(".fseventsd") ||
                shortName.equals(".Trashes") ||
                shortName.equals("._.Trashes") ||
                shortName.equals(".DS_Store")) {
                file = dir.openNextFile();
                continue;
            }
            
            fileCount++;
            
            html += "<li class='file-item'>";
            html += "<span class='file-name ";
            html += file.isDirectory() ? "folder" : "file";
            html += "'>";
            
            if (file.isDirectory()) {
                html += "📁 <a href='/?path=" + fullPath + "'>" + shortName + "</a>";
            } else {
                html += "<a href='/download?file=" + fullPath + "'>";
                if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
                    html += "🖼️ ";
                } else if (fileName.endsWith(".txt") || fileName.endsWith(".log")) {
                    html += "📝 ";
                } else {
                    html += "📄 ";
                }
                html += shortName + "</a>";
            }
            
            html += "</span>";
            
            if (!file.isDirectory()) {
                html += "<span class='file-size'>" + formatFileSize(file.size()) + "</span>";
            } else {
                html += "<span class='file-size'>—</span>";
            }
            
            html += "<div class='file-actions'>";
            if (!file.isDirectory()) {
                html += "<a href='/download?file=" + fullPath + "' class='btn btn-primary'>Download</a>";
                if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
                    html += "<a href='/view?file=" + fullPath + "' class='btn btn-secondary'>View</a>";
                }
            }
            html += "<a href='/delete?file=" + fullPath + "' class='btn btn-danger' onclick='return confirm(\"Are you sure you want to delete \\\"" + shortName + "\\\"?\")'>Delete</a>";
            html += "</div></li>";
            
            file = dir.openNextFile();
        }
    }

    if (fileCount == 0) {
        html += R"=====(
            <li class="no-files">
                <p>No files or folders found.</p>
                <p>This directory is empty or contains only hidden system files.</p>
            </li>
        )=====";
    }

    html += R"=====(
        </ul>
    </div>

    <script>
        // 确认删除对话框
        function confirmDelete(filename) {
            return confirm('Are you sure you want to delete "' + filename + '"?');
        }
        
        // 自动刷新页面（可选）
        setTimeout(function() {
            window.location.reload();
        }, 30000); // 每30秒刷新一次
    </script>
</body>
</html>
    )=====";

    fileServer.send(200, "text/html", html); });

    // 文件下载
    fileServer.on("/download", HTTP_GET, []()
                  {
    String filePath = fileServer.arg("file");
    filePath = normalizePath(filePath);
    if (SD_MMC.exists(filePath)) {
      File file = SD_MMC.open(filePath, FILE_READ);
      fileServer.sendHeader("Content-Type", "application/octet-stream");
      fileServer.sendHeader("Content-Disposition", "attachment; filename=" + getFileName(filePath));
      fileServer.streamFile(file, "application/octet-stream");
      file.close();
    } else {
      fileServer.send(404, "text/plain", "File not found");
    } });

    // 图片查看
    fileServer.on("/view", HTTP_GET, []()
                  {
    String filePath = fileServer.arg("file");
    filePath = normalizePath(filePath);
    if (SD_MMC.exists(filePath) && (filePath.endsWith(".jpg") || filePath.endsWith(".jpeg"))) {
      File file = SD_MMC.open(filePath, FILE_READ);
      fileServer.sendHeader("Cache-Control", "public, max-age=3600");
      fileServer.streamFile(file, "image/jpeg");
      file.close();
    } else {
      fileServer.send(404, "text/plain", "Image not found or unsupported format");
    } });

    // 文件删除
    fileServer.on("/delete", HTTP_GET, []()
                  {
    String filePath = fileServer.arg("file");
    filePath = normalizePath(filePath);
    if (SD_MMC.exists(filePath)) {
      if (SD_MMC.remove(filePath)) {
        fileServer.send(200, "text/plain", "File deleted successfully: " + getFileName(filePath));
      } else {
        fileServer.send(500, "text/plain", "Failed to delete file");
      }
    } else {
      fileServer.send(404, "text/plain", "File not found");
    }
    
    // 重定向回文件管理器
    fileServer.sendHeader("Location", "/", true);
    fileServer.send(302, "text/plain", ""); });

    fileServer.begin();
    Serial.println("✅ HTTP File Server started on port 8080");
}

void handleHttpFileServer()
{
    fileServer.handleClient();
}

String getFileName(String path)
{
    int lastSlash = path.lastIndexOf('/');
    if (lastSlash != -1)
    {
        return path.substring(lastSlash + 1);
    }
    return path;
}

String formatFileSize(uint64_t bytes)
{
    if (bytes < 1024)
        return String(bytes) + " B";
    else if (bytes < 1024 * 1024)
        return String(bytes / 1024.0, 1) + " KB";
    else if (bytes < 1024 * 1024 * 1024)
        return String(bytes / (1024.0 * 1024.0), 1) + " MB";
    else
        return String(bytes / (1024.0 * 1024.0 * 1024.0), 1) + " GB";
}
String getBreadcrumb(String path)
{
    if (path == "/" || path.isEmpty())
        return "";

    String breadcrumb;
    String currentPath = "";

    // 分割路径
    int start = 0;
    if (path.startsWith("/"))
        start = 1; // 跳过根斜杠

    int end = path.indexOf('/', start);

    while (end != -1)
    {
        String segment = path.substring(start, end);
        currentPath += "/" + segment;
        breadcrumb += " / <a href='/?path=" + currentPath + "'>" + segment + "</a>";

        start = end + 1;
        end = path.indexOf('/', start);
    }

    // 处理最后一段
    if (start < path.length())
    {
        String segment = path.substring(start);
        currentPath = path; // 使用完整路径
        breadcrumb += " / <a href='/?path=" + currentPath + "'>" + segment + "</a>";
    }

    return breadcrumb;
}